package bmt.audioplayer.app.util;

import android.content.ContentResolver;
import android.content.Context;
import android.database.Cursor;
import android.media.MediaMetadataRetriever;
import android.net.Uri;
import android.os.Environment;
import android.provider.MediaStore;

import java.io.File;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;

import bmt.audioplayer.app.R;
import bmt.audioplayer.app.model.player.Song;

/**
 * Created by Tuan on 4/20/14.
 */
public class SongManager implements Serializable {
    final String MEDIA_PATH = Environment.getExternalStorageDirectory()
            .getPath() + "/";

    private String allSongsInSDSelection = MediaStore.Audio.Media.IS_MUSIC + "!=0";
    private String extensionSelection = "(" + MediaStore.Audio.Media.DATA + " LIKE ? OR " + MediaStore.Audio.Media.DATA + " LIKE ? )";
    private String getSongByName = "(" + MediaStore.Audio.Media.ARTIST + " LIKE ? OR " + MediaStore.Audio.Media.TITLE + " LIKE ? )";
    private String orderByName = MediaStore.Audio.Media.TITLE + " ASC";
    private String[] extensionArg = {"%mp3", "%wma"};
    private String[] projection = {
            MediaStore.Audio.Media._ID,
            MediaStore.Audio.Media.TITLE,
            MediaStore.Audio.Media.ARTIST,
            MediaStore.Audio.Media.DATA,
            MediaStore.Audio.Media.DISPLAY_NAME,
            MediaStore.Audio.Media.DURATION
    };

    private ArrayList<Song> songsList = new ArrayList<Song>();
    private ArrayList<Integer> oriList = new ArrayList<Integer>();
    private ArrayList<Integer> playList = new ArrayList<Integer>();
    private ArrayList<Integer> randomList = new ArrayList<Integer>();
    int currentIndex = 0;
    boolean isRepeat = false;
    boolean isShuff = false;
    boolean isFirstTime = true;
    ContentResolver contentResolver;

    private Context context;

    MediaMetadataRetriever mediaMetadataRetriever;

    // Constructor
    public SongManager(Context context) {
        this.context = context;
        mediaMetadataRetriever = new MediaMetadataRetriever();
        contentResolver = context.getContentResolver();
        getAllSongs();
    }

    public ArrayList<Song> getAllSongs() {
        String selection = allSongsInSDSelection + " AND " + extensionSelection;
        Cursor cursor = contentResolver.query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, projection, selection, extensionArg, orderByName);

        return getSongByCursor(cursor);
    }

    public ArrayList<Song> getSongBySearch(String query) {
        String selection = getSongByName + " AND " + extensionSelection;
        String[] arg = {"%"+query+"%", "%"+query+"%", extensionArg[0], extensionArg[1]};
        Cursor cursor = contentResolver.query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, projection, selection, arg, orderByName);
        return  getSongByCursor(cursor);
    }

    public ArrayList<Song> getSongByCursor(Cursor cursor) {
        if (cursor.getCount() > 0) {
            resetAttribute();

            cursor.moveToFirst();
            Song song;
            while (cursor.isAfterLast() == false) {
                String id = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media._ID));
                String title = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.TITLE));
                String artist = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ARTIST));
                String path = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DATA));
                String displayName = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DISPLAY_NAME));
                long duration = cursor.getLong(cursor.getColumnIndex(MediaStore.Audio.Media.DURATION));
                title = (title != null && !title.equals("<unknown>")) ? title : "#Nameless";
                artist = (artist != null && !artist.equals("<unknown>")) ? artist : "#Nameless";
                song = new Song(id, path, title, artist, displayName, duration);
                songsList.add(song);
                oriList.add(songsList.size() - 1);
                cursor.moveToNext();
            }
            playList = (ArrayList) oriList.clone();
        }
        cursor.close();
        return songsList;
    }


    public void resetAttribute() {
        songsList.clear();
        oriList.clear();
        playList.clear();
        randomList.clear();
        currentIndex = 0;
        isFirstTime = true;
    }

    public byte[] getSongPicture(String path) {
        Uri uri = Uri.fromFile(new File(path));
        mediaMetadataRetriever.setDataSource(context, uri);
        return mediaMetadataRetriever.getEmbeddedPicture();
    }

    public Song getPlaySong() {
        Song song = songsList.get(playList.get(currentIndex));
        if (song.getImg() == null) {
            song.setImg(getSongPicture(song.getPath()));
        }
        return song;
    }

    public int calculateSongIndex(int action) {
        int index = 0;
        if (isRepeat == true) {
            index = currentIndex;
        } else {
            if (action == R.id.player_btn_next) {
                if (currentIndex == playList.size() - 1) {
                    index = 0;
                } else {
                    index = currentIndex + 1;
                }
            } else if (action == R.id.player_btn_pre) {
                if (currentIndex == 0) {
                    index = playList.size() - 1;
                } else {
                    index = currentIndex - 1;
                }
            }
        }
        currentIndex = index;
        return index;
    }

    public int calculateMoveToSongIndex(int index) {
        int moveIndex = 0;
        // Get index by ori list
        int oriIndex = oriList.get(oriList.indexOf(index));
        // Convert index to playlist
        moveIndex = playList.indexOf(oriIndex);
        return moveIndex;
    }

    public int moveToSong(int index) {
        currentIndex = index;
        return index;
    }

    public void resetPlaylist() {
        playList = (ArrayList<Integer>) oriList.clone();
    }

    public void shuffPlaylist() {
        if (randomList.size() == 0) {
            randomList = (ArrayList<Integer>) oriList.clone();
            Collections.shuffle(randomList);
        }
        playList = randomList;
    }

    public void resetCurrentIndex(int index) {
        currentIndex = playList.indexOf(index);
    }

    public String getMEDIA_PATH() {
        return MEDIA_PATH;
    }

    public ArrayList<Song> getSongsList() {
        return songsList;
    }

    public void setSongsList(ArrayList<Song> songsList) {
        this.songsList = songsList;
    }

    public ArrayList<Integer> getOriList() {
        return oriList;
    }

    public void setOriList(ArrayList<Integer> oriList) {
        this.oriList = oriList;
    }

    public ArrayList<Integer> getPlayList() {
        return playList;
    }

    public void setPlayList(ArrayList<Integer> playList) {
        this.playList = playList;
    }

    public ArrayList<Integer> getRandomList() {
        return randomList;
    }

    public void setRandomList(ArrayList<Integer> randomList) {
        this.randomList = randomList;
    }

    public int getCurrentIndex() {
        return currentIndex;
    }

    public void setCurrentIndex(int currentIndex) {
        this.currentIndex = currentIndex;
    }

    public boolean isRepeat() {
        return isRepeat;
    }

    public void setRepeat(boolean isRepeat) {
        this.isRepeat = isRepeat;
    }

    public boolean isShuff() {
        return isShuff;
    }

    public void setShuff(boolean isShuff) {
        this.isShuff = isShuff;
    }

    public Context getContext() {
        return context;
    }

    public void setContext(Context context) {
        this.context = context;
    }

    public MediaMetadataRetriever getMediaMetadataRetriever() {
        return mediaMetadataRetriever;
    }

    public void setMediaMetadataRetriever(MediaMetadataRetriever mediaMetadataRetriever) {
        this.mediaMetadataRetriever = mediaMetadataRetriever;
    }

    public boolean isFirstTime() {
        return isFirstTime;
    }

    public void setFirstTime(boolean isFirstTime) {
        this.isFirstTime = isFirstTime;
    }
}
